package xchange;

/**
 * Class represents the router i/f 
 * in other words : handles router interaction
 */
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.HashMap;

public class Router {

	public String ip = "";
	public final int port = 7000;

	private Socket s = null;
	private PrintWriter out = null;
	private BufferedReader in = null;

	private ArrayList<Fileinfo> downloadList;
	private FileInfoParser fp;
	private RouterListener rl;

	/**
	 * Default constructor
	 */
	public Router() {
		downloadList = new ArrayList<Fileinfo>();
		fp = new FileInfoParser();
	}

	/**
	 * Method that sends a command to the router
	 * 
	 * @param downloadList
	 *            - Fileinfo objects that needs to be downloaded
	 */
	public void takeOverDownload(ArrayList<Fileinfo> downloadList) {
		this.downloadList = downloadList;

		if (downloadList.isEmpty() != true) {
			connectToRouter();
			for (int i = 0; i < downloadList.size(); i++) {
				// Send fileInfoString generated from parser
				out.println(fp.parse(downloadList.get(i)));
				out.println("EOC");
			}
		}
	}

	/**
	 * Connect to the router. Setup a socket connection
	 */
	private void connectToRouter() {
		try {
			// local loopback
			if (s == null) {
				s = new Socket(ip, port);

				// get socket input stream and open a BufferedReader on it
				in = new BufferedReader(new InputStreamReader(s
						.getInputStream()));

				// get socket output stream and open a PrintWriter on it
				out = new PrintWriter(s.getOutputStream(), true);
			}
		} catch (UnknownHostException e) {
			System.err.println("Host unknown");
		} catch (IOException e) {
			System.out.println("No connection");
			System.err.println("I/O error");
		}
	}

	// tell router to stop downloading
	public void stopDownload() {
		if (s == null) {
			connectToRouter();
		}

		out.println("STOP-DOWNLOAD");
		out.println("EOC");
		getRtInfoFiles();
	}

	// get all info files from router and merge them with local info files
	public void getRtInfoFiles() {
		if (s == null) {
			connectToRouter();
		}
		out.println("GET-RT-INFO-FILES");
		out.println("EOC");
		rl = new RouterListener(in, fp);
		rl.listen();

		HashMap<String, ArrayList<Integer>> blocksToDownload = fp
				.compareFileInfoFiles();

		// Receive files
		for (String key : blocksToDownload.keySet()) {
			ArrayList<Integer> tmp = blocksToDownload.get(key);

			for (int i = 0; i < tmp.size(); i++) {
				getRouterFile(key, tmp.get(i));
			}
		}
	}

	// remove all info files from router
	public void removeRtInfoFiles() {
		if (s == null) {
			connectToRouter();
		}
		out.println("REMOVE-INFO-FILES");
		out.println("EOC");
	}

	// get file by block nr
	public void getRouterFile(String filename, int block_nr) {
		if (s == null) {
			connectToRouter();
		}
		out.println("GET-FILE " + filename + " " + block_nr);
		out.println("EOC");
		rl.listen();
	}
}
